package com.utils.load
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObjectContainer;
	import flash.display.Loader;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.net.URLRequest;
	
	/**
	 * 全局可使用的加载管理器 主要目的将种子变成实体
	 * @author Administrator
	 */	
	
	public class LoadManager
	{
		public static const LOAD_OVER:String = "LOAD_OVER";
		
		private static var loader:Loader = new Loader(); 
		
		//加载器只有一个 同一时间只能加载一个 
		//如需要重复加载 先将种子全部存入数组 等当前加载进度完成再加载下一个种子即可
		
		private static var resultUrl:String;
		
		private static var result:Function;
		
		private static var resultContain:DisplayObjectContainer; //纪录当前种子对应的容器
		
		private static var isLoading:Boolean = false; //纪录当前加载状态是否在加载
		
		private static var loadList:Array = []; //暂存未加载的种子
		
		/**
		 * 让外部侦听此事件 将事件的回调函数传入
		 * @param func 外部传入的回调函数
		 */		
		public static function addLoadOver(func:Function):void{
			loader.addEventListener(LoadManager.LOAD_OVER , func);
		}
		
		/**
		 * 让外部停止侦听此事件 将事件的回调函数传入
		 * @param func 外部传入的回调函数
		 */	
		public static function removeLoadOver(func:Function):void{
			loader.removeEventListener(LoadManager.LOAD_OVER , func);
		}
		
		/**
		 *     		{	url
		 *  loadObj   	loadFunction
		 * 				contain   }
		 * 
		 * 加载目标地址 处理加载完成后的事情
		 * @param url 种子地址
		 * @param loadFunction 加载完了目标需要执行的函数
		 * @param contain 加载完了需要让种子内容显示的容器(可选) 片子的父容器
		 */		
		public static function loadSource(url:String ,loadFunction:Function = null , contain:DisplayObjectContainer = null):void{
			var loadObj:LoadObject = new LoadObject(); //通过创建自定义Object绑定两个数据
			loadObj.url = url;
			loadObj.loadFunction = loadFunction;
			
			loadObj.contain = contain;
			
			loadList.push(loadObj); //种子先排队
			loadUrl();
			//result = loadFunction;
		}
		
		/**
		 * 对目标地址进行加载 loader.load(url)  loadComplete
		 * @param url
		 */		
		private static function loadUrl():void{
			if(loadList.length == 0){ //判断种子集合是全部变成片子了
				wait();
				return;
			}
			if(isLoading == true){
				return; //判断是否已经有线程在加载
			}
			
			var loadObj:LoadObject = loadList.shift();
			//下面取出最新数据
			resultUrl = loadObj.url; //存储当前种子地址
			
			result = loadObj.loadFunction; //存储当前种子对应的回调函数
			
			resultContain = loadObj.contain; //存储当前种子对应的容器
			
			if(ResourceBox.cotainKey(loadObj.url)){ //如果已经在内存里面找到了 就不加载
				//将已存在的位图信息复制一份位图出来 给回调函数调用
				trace("从素材池里面取" + loadObj.url);
				var bitmapData:BitmapData = ResourceBox.getResource(loadObj.url);
				var bitmap:Bitmap = new Bitmap(bitmapData); //将源图像序列给新的位图去显示
				loadOver(bitmap);
				return;
			}
			
			trace("开始加载了" + loadObj.url);
			loader.load(new URLRequest(loadObj.url));
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE,loadComplete);
			loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,ioHandler);
			isLoading = true; //一旦此线程种子开始加载 标记正在加载
		}
		
		/**
		 * 只能通过loader发出事件 因为wait是静态方法(类调用的方法) 
		 * 在静态方法中不存在this 因为this是通过此类创造的实例对象
		 * 所以无法在静态方法中调用通过this的实例方法dispatchEvent
		 * 而loader已经是实例对象 且继承EventDispatcher事件发送者 所以是发送的合适人选
		 */
		private static function wait():void
		{
			loader.contentLoaderInfo.removeEventListener(Event.COMPLETE,loadComplete);
			loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR,ioHandler);
			loader.unload(); //断开和片子的联系
			
			if(loader.hasEventListener(LoadManager.LOAD_OVER)){
				loader.dispatchEvent(new Event(LoadManager.LOAD_OVER)); //发出加载完成事件
			}
		}
		
		/**
		 * 当图片无法加载的时候也要驱动加载下一张图片
		 * @param e
		 */		
		private static function ioHandler(e:IOErrorEvent):void
		{
			trace("加载错误：  " + e); //加载错误的时候直接跳过当前种子 加载下一个种子
			isLoading = false; //当此线程种子加载完成 标记可以继续加载
			
			loadUrl(); //继续执行下一个加载线程
		}
		
		/**
		 * loadComplete方法执行调用外部传入的函数
		 * loader.content获取实体(片) 当做参数执行回调
		 * 加载完成后还要继续加载下一个种子
		 */		
		private static function loadComplete(e:Event):void{
			var bitmap:Bitmap = loader.content as Bitmap;
			
			ResourceBox.setResource(resultUrl,bitmap.bitmapData); //存入最新的数据
			
			loadOver(bitmap);
		}
		
		/**
		 * 加载结束处理当前片子 决定该片子的去留(卖给厂商)
		 * @param bitmap 片子
		 */		
		private static function loadOver(bitmap:Bitmap):void{
			if(result != null){ //如果传入第二个参数才执行 否则报空指针
				if(resultContain != null){ //如果传入第三个参数
					result(bitmap,resultContain); //如果第三个参数传入 也将自己作为参数传出
				}else{
					result(bitmap);
				}
			}
			isLoading = false; //当此线程种子加载完成 标记可以继续加载
			loadUrl(); //继续执行下一个加载线程
		}
		
		
		
		
		
		
		
		
		
	}
}